package com.tang.websocket.v1.session;

import com.tang.websocket.v1.message.WebSocketMessage;

import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Tang
 * @classname ConcurrentWebSocketSessionDecorator
 * @description [ 处理并发 ]
 * @date 2022/11/29 10:23
 */
public class ConcurrentWebSocketSessionDecorator extends WebSocketSessionDecorator {

    /**
     * messageQueue
     */
    private final Queue<WebSocketMessage<?>> messageQueue = new ArrayBlockingQueue<>(64);

    /**
     * 策略
     */
    private final OverFlowStrategy strategy;

    private final Lock flushLock = new ReentrantLock();

    private final WebSocketSession proxyWebSocketSession;

    public ConcurrentWebSocketSessionDecorator(WebSocketSession proxyWebSocketSession) {
        this(proxyWebSocketSession, OverFlowStrategy.DROP);
    }

    public ConcurrentWebSocketSessionDecorator(WebSocketSession proxyWebSocketSession,OverFlowStrategy strategy) {
        super(proxyWebSocketSession);
        this.strategy = strategy;
        this.proxyWebSocketSession = proxyWebSocketSession;
    }

    @Override
    public void sendMessage(WebSocketMessage<?> message) throws IOException {
        this.messageQueue.add(message);
        try {
            this.flushLock.lock();
            do {
                WebSocketMessage<?> poll = this.messageQueue.poll();
                if (poll == null) {
                    return;
                }
                try {
                    proxyWebSocketSession().sendMessage(poll);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } while (!this.messageQueue.isEmpty());
        } finally {
            this.flushLock.unlock();
        }
    }

    public WebSocketSession proxyWebSocketSession() {
        return proxyWebSocketSession;
    }

    public enum OverFlowStrategy {
        /**
         * DROP
         */
        DROP,
        /**
         * TERMINATE
         */
        TERMINATE
    }


}
